﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Practices.ServiceLocation;
using Pap.Core.Utilities;
using Pap.Data;
using Pap.Data.Abstraction.Utils;
using Pap.Services;
using Pap.Services.WorkflowEngine;
using Pap.Web.Utils;

namespace Pap.Web.Modules.Loan.ViewModel
{
    /// <summary>
    /// 
    /// </summary>
    public class ExpertWaitingListControlViewModel : IViewModel
    {
        /// <summary>
        /// 
        /// </summary>
        public const int RESPDEC = 1;
        /// <summary>
        /// 
        /// </summary>
        public const int RETURN = 2;

        /// <summary>
        /// 
        /// </summary>
        ILoanRepository _LoanRepository;
        /// <summary>
        /// 
        /// </summary>
        IWorkflowService _WfService;
        /// <summary>
        /// 
        /// </summary>
        IAdministrationRepository _AdministrationRepository;

        /// <summary>
        /// Initializes a new instance of the <see cref="ExpertWaitingListControlViewModel"/> class.
        /// </summary>
        /// <param name="loanRepo">The loan repo.</param>
        /// <param name="wf">The wf.</param>
        /// <param name="adminRepository">The admin repository.</param>
        public ExpertWaitingListControlViewModel(ILoanRepository loanRepo, IWorkflowService wf, IAdministrationRepository adminRepository)
        {
            this._LoanRepository = loanRepo;
            this._WfService = wf;
            this._AdministrationRepository = adminRepository;
        }

        /// <summary>
        /// Gets the expert waiting list.
        /// </summary>
        /// <returns></returns>
        public IEnumerable GetExpertWaitingList()
        {
            var loansEntitiesIDs = _WfService.GetInStep(Steps.ExpertWaitingList);
            IEnumerable<IProject> userProjects = _AdministrationRepository.GetUserProjects(RegistryInfo.UserID);

            var loans = _LoanRepository.FindCustomerLoans(loan => loansEntitiesIDs.Contains(loan.LoanID));
            loans = loans.Where(loan=> userProjects.Contains(loan.ProjectStage.ProjectObj));
            return loans.Select(loan => new
                {
                    LoanID = loan.LoanID,
                    CustomerName = loan.CustomerObj.CustomerName,
                    LoanAmount = loan.LoanAmount,
                    LoanCreatedDate = loan.LoanCreatedDate,
                    LoanNumber = loan.LoanNumber,
                    LoanPaymentMethod = loan.LoanPaymentMethodObj.LoanPaymentMethodName,
                    LoanPaymentPeriod = loan.LoanPaymentPeriod,
                    LoanType = loan.LoanTypeObj.Name,
                    ProposedAmount = loan.FeasibilityStudyObj != null ? loan.FeasibilityStudyObj.LoanAmount : loan.LoanAmount,
                    ProposedPaymentMethod = loan.FeasibilityStudyObj != null ? _LoanRepository.GetLoanPaymentMethodByID(loan.FeasibilityStudyObj.LoanPaymentMethodID).LoanPaymentMethodName : loan.LoanPaymentMethodObj.LoanPaymentMethodName,
                    ProposedPaymentPeriod = loan.FeasibilityStudyObj != null ? loan.FeasibilityStudyObj.LoanPaymentPeriod : loan.LoanPaymentPeriod,
                    LoanStatus = _WfService.GetStep(_WfService.GetProcessInstanceIDByEntity(loan.LoanID)).DisplayName.ToString(),
                    PerviousNotes = _WfService.GetStep(_WfService.GetProcessInstanceIDByEntity(loan.LoanID)).PreviousNotes
                }).OrderBy(loan => loan.LoanNumber);
        }

        /// <summary>
        /// Gets the available actions.
        /// </summary>
        /// <returns></returns>
        public IEnumerable<ActionTypes> GetAvailableActions()
        {
            return _WfService.GetAvailableActionsByStep(Steps.ExpertWaitingList);
        }

        /// <summary>
        /// Takes the decision.
        /// </summary>
        /// <param name="loanId">The loan id.</param>
        /// <param name="action">The action.</param>
        /// <param name="notes">The notes.</param>
        public void TakeDecision(Guid loanId, ActionTypes action, string notes)
        {
            Guid processInstanceId = _WfService.GetProcessInstanceIDByEntity(loanId);
            _WfService.Move(action, processInstanceId, RegistryInfo.UserID, notes, null);
        }

        /// <summary>
        /// Takes the loan decisions.
        /// </summary>
        /// <param name="loansIDs">The loans I ds.</param>
        /// <param name="loanDecisions">The loan decisions.</param>
        /// <param name="Notes">The notes.</param>
        public void TakeLoanDecisions(List<Guid> loansIDs, List<int> loanDecisions, List<string> Notes)
        {
            using (var trancaction = ServiceLocator.Current.GetInstance<IUnitOfWork>())
            {
                for (int i = 0; i < loanDecisions.Count; i++)
                {
                    ICustomerLoan loan = _LoanRepository.GetCustomerLoanByID(loansIDs[i]);
                    Guid processInstanceId = _WfService.GetProcessInstanceIDByEntity(loansIDs[i]);
                    if (loanDecisions[i] == RESPDEC)
                    {
                        var step = _WfService.GetStep(processInstanceId);
                        _WfService.Move(step.ActionType, processInstanceId, RegistryInfo.UserID, Notes[i], step.CompletionDate);

                    }
                    else
                        if (loanDecisions[i].Equals(RETURN))
                        {
                            _WfService.Move(ActionTypes.Return, processInstanceId, RegistryInfo.UserID, Notes[i], null);
                        }


                }

                trancaction.Commit();
            }
        }
    }
}
